package top.cyuw.simplerpc.remoting.server;

import lombok.extern.slf4j.Slf4j;
import top.cyuw.simplerpc.exception.RpcException;
import top.cyuw.simplerpc.registry.ServiceRegistry;
import top.cyuw.simplerpc.dto.RpcRequest;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author chen
 * @date 2023/3/14 21:16
 */
@Slf4j
public class InvokeHandler {

    private final ServiceRegistry serviceRegistry;

    public InvokeHandler(ServiceRegistry serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
    }

    public Object handle(RpcRequest rpcRequest) {
        Object service = serviceRegistry.getService(rpcRequest.getFullServiceName());
        if (service == null) {
            throw new RpcException("could not found service: " + rpcRequest.getFullServiceName());
        }
        return invokeTargetMethod(rpcRequest, service);
    }

    private Object invokeTargetMethod(RpcRequest rpcRequest, Object service) {
        try {
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
            return method.invoke(service, rpcRequest.getParameters());
        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
            throw new RpcException("invoke target method failed: " + e.getMessage(), e);
        }
    }

}
